package co.edu.eam.taller.mecanico.ejbs;

import java.util.Date;
import java.util.List;

import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import co.edu.eam.taller.mecanico.entidades.Automovil;
import co.edu.eam.taller.mecanico.entidades.Cliente;
import co.edu.eam.taller.mecanico.entidades.Detalle_Visita;
import co.edu.eam.taller.mecanico.entidades.Detalle_VisitaPK;
import co.edu.eam.taller.mecanico.entidades.Repuesto;
import co.edu.eam.taller.mecanico.entidades.Visita;

/**
 * Session Bean para administrar lo realizado en el taller
 */
@Stateless
@LocalBean
public class TallerBean {
	/**
	 * Entity manager para las transacciones
	 */
	@PersistenceContext
	private EntityManager entityManager;

	public TallerBean() {
		super();
	}
	/* Metodos para operaciones*/
	public double calcularTotalRepuesto(long idRepuesto,int cantidad){
		Repuesto rep= buscarRepuestoPorCodigo(idRepuesto);
		double total= rep.getPrecio()*cantidad;
		return total;
	}
	public double calcularTotalVisita(List<Detalle_Visita>detalles){
		
		double total=0;
		if(detalles!=null){
			for (Detalle_Visita detalle_Visita : detalles) {
				total+=calcularTotalRepuesto(detalle_Visita.getRepuesto().getCodigo(), detalle_Visita.getCantidad());
			}
		}
		return total;
	}
	/* Metodos para listar */
	/**
	 * metodo para listar los detalles realizados en una visita especifica.
	 * @param idVisita parametro que especifica la visita a la cual se le consultaran los detalles.
	 * @return una lista de Dtalles_Visita pertenecientes a la visita del parametro.
	 */
	@SuppressWarnings("unchecked")
	public List<Detalle_Visita>listarDetallesPorVisita(long idVisita){
		
		Query q=entityManager.createNamedQuery(Detalle_Visita.FIND_BY_VISITA);
		q.setParameter(Detalle_Visita.PARAMETRO_VISITA, idVisita);
		
		List<Detalle_Visita>list=q.getResultList();
		if(list==null){
			return null;
		}else {
			return q.getResultList();
		}
		
	}
	/**
	 * Metodo para listar los detalles de todas las visitas.
	 * @return una lista de detalles de todas las visitas.
	 */
	@SuppressWarnings("unchecked")
	public List<Detalle_Visita>listarDetalles(){
		Query q=entityManager.createNamedQuery(Detalle_Visita.FIND_ALL);
		return q.getResultList();
	}
	/**
	 * metodo para listar los repuestos persistidos en la base de datos
	 * @return una lista de repuestos almacenados en la base de datos.
	 */
	@SuppressWarnings("unchecked")
	public List<Repuesto>listarRepuestos(){
		Query q=entityManager.createNamedQuery(Repuesto.CONSULTA_TODOS);
		return q.getResultList();
	}
	/**
	 * Metodo para listar todos los clientes almacenados en la base de datos.
	 * @return retorna una lista de clientes almacenados en la base de datos.
	 */
	@SuppressWarnings("unchecked")
	public List<Cliente>listarClientes(){
		Query q=entityManager.createNamedQuery(Cliente.CONSULTA_TODOS);
		List<Cliente>clientes= q.getResultList();
		if(clientes==null){
			return null;
		}else {
			return clientes;
		}
	}
	/**
	 * metodo para listar las visitas de un auto registrado.
	 * @param idAuto parametro que indica el auto al cual se le buscaran las visitas.
	 * @return una lista con las visitas registradas del auto buscado.
	 */
	@SuppressWarnings("unchecked")
	public List<Visita>listarVisitasPorAuto(long idAuto){
		if(idAuto==0){
			return null;
		}
		Query q=entityManager.createNamedQuery(Visita.FIND_VISITA_BY_AUTOMOVIL);
		q.setParameter(Visita.PARAMETRO_Automovil, buscarAutomovilPorID(idAuto));
		List<Visita>visitas= q.getResultList();
		if(visitas==null){
			return null;
		}
		return q.getResultList();
	}
	/**
	 * Metodo para listar los automoviles pertenecientes a un cliente en la base de datos del taller.
	 * @param <idCliente> el parametro que guarda el identificador del cliente al cual se le buscan sus autos. 
	 * @return una lista de automoviles los cuales tienen en comun el <idCliente>.
	 */
	@SuppressWarnings("unchecked")
	public List<Automovil>listarAutomovilesDeCliente(long idCliente){
		Query q = entityManager.createNamedQuery(Automovil.CONSULTA_AUTOMOVILES_BY_CLIENTE);
		q.setParameter(Automovil.PARAMETRO_CLIENTE, idCliente);
		return q.getResultList();
	}
	
	/* Metodos para registrar en la base de datos */
	/**
	 * Metodo para registrar un nuevo cliente en el taller.
	 * @param nombre parametro que almacena el registro del nombre del nuevo cliente.
	 * @param cedula parametro que almacena el registro de la cedula del nuevo cliente.
	 */
	public void crearCliente(String nombre,String cedula){
		entityManager.persist(new Cliente(nombre, cedula));
	}
	/**
	 * Metodo para registrar un nuevo repuesto en el taller.
	 * @param codigo parametro que almacena el registro del codigo del nuevo repuesto.
	 * @param nombre parametro que almacena el registro del nombre del nuevo repuesto.
	 * @param precio parametro que almacena el registro del precio del nuevo repuesto.
	 */
	public void crearRepuesto(long codigo, String nombre, double precio){
		entityManager.persist(new Repuesto(codigo, nombre, precio));
	}
	/**
	 * Metodo para registrar un nuevo automovil a un cliente actual.
	 * @param placa parametro que almacena el registro de la placa del nuevo automovil. 
	 * @param modelo parametro que almacena el registro del modelo del nuevo automovil.
	 * @param marca parametro que almacena el registro de la marca del nuevo automovil.
	 * @param cliente parametro que almacena el registro del cliente al que pertenece el nuevo automovil.
	 */
	public void registrarAutomovil(String placa, String modelo, String marca,
			long cliente){
		entityManager.persist(new Automovil(placa, modelo, marca, buscarClientePorID(cliente)));
	}
	/**
	 * Metodo para registrar una visita a un automovil registrado.
	 * @param fecha_Mora parametro que indica la fecha de mora de la visita a crearse.
	 * @param automovil parametro que indica el id del automovil al que se le realizara la visita.
	 */
	public void registrarVisita(Date fecha_Mora, long automovil){
		entityManager.persist(new Visita(fecha_Mora, buscarAutomovilPorID(automovil)));
	}
	/**
	 * Metodo para registrar un detalle de una visita previamente registrada en la base de datos del taller.
	 * @param cantidad parametro que indica la cantidad del repuesto solicitado en esta visita.
	 * @param repuesto parametro que indica el repuesto solicitado en esta visita.
	 * @param visita parametro que indica el id de la visita a la cual se solicita el repuesto.
	 */
	public void registrarDetallesVisita(int cantidad, long repuesto, long visita){
		Detalle_Visita detx=buscarDetallePorVisitaYRepuesto(visita, repuesto);
		if(detx!=null){
			detx.setCantidad(detx.getCantidad()+cantidad);
			entityManager.merge(detx);
		}else {

			Detalle_VisitaPK detPK=new Detalle_VisitaPK(repuesto, visita);
			 Detalle_Visita det=new Detalle_Visita(detPK,cantidad, buscarRepuestoPorID(repuesto), buscarVisitaPorID(visita));
			entityManager.persist(det);
		}
		
	}
	/* Metodos para buscar */
	/**
	 * Metodo para buscar un repuesto por su codigo.
	 * @param <id> el codigo del repuesto que queremos hallar
	 * @return el repuesto cuyo codigo corresponde a <id>. o null en caso de no existir.
	 */
	public Repuesto buscarRepuestoPorCodigo(long id){
		
		Repuesto rep= entityManager.find(Repuesto.class, id);
		if(rep==null){
			return null;
		}else {
			return rep;
		}
	}
	 
	/**
	 * Metodo para buscar un detalle por visita y repuesto.
	 * @param <visita> Parametro que corresponde al id de la visita del detalle que estamos buscando.
	 * @param <repuesto> Parametro que corresponde al id del repuesto del detalle que estamos buscando.
	 * @return <det> El Detalle_Visita correspondiente al parametro <visita> y <repuesto>. o null de no existir tal detalle.
	 */
	public Detalle_Visita buscarDetallePorVisitaYRepuesto(long visita,long repuesto){
		Query q= entityManager.createNamedQuery(Detalle_Visita.FIND_BY_VISITA_AND_REPUESTO);
		q.setParameter(Detalle_Visita.PARAMETRO_VISITA, visita);
		q.setParameter(Detalle_Visita.PARAMETRO_REPUESTO, repuesto);
		if(q.getResultList().isEmpty()){
			return null;
		}
		
		Detalle_Visita det=(Detalle_Visita) q.getResultList().get(0);
		if(det==null){
			return null;
		}else {
			return det;
		}
	}
	/**
	 * Metodo para buscar una visita por su id.
	 * @param <id> parametro el cual identifica la visita que vamos a buscar. 
	 * @return la visita con el identificador <id> correcto.
	 */
	public Visita buscarVisitaPorID(long id){
		return entityManager.find(Visita.class, id);
	}
	/**
	 * Metodo para buscar un cliente por su id registrado en el taller.
	 * @param <id> parametro que contiene el id del cliente necesitado.
	 * @return el cliente con el <id> solicitado en el parametro. 
	 */
	public Cliente buscarClientePorID(long id){
		return entityManager.find(Cliente.class, id);
	}
	/**
	 * Metodo para buscar un cliente por su cedula registrado en el taller.
	 * @param <cedula> parametro que contiene la cedula del cliente necesitado.
	 * @return el cliente con el <cedula> solicitado en el parametro. 
	 */
	public Cliente buscarClientePorCedula(String cedula)throws Exception{
		Query q= entityManager.createNamedQuery(Cliente.FIND_CLIENTE_BY_CEDULA);
		q.setParameter(Cliente.PARAMETRO_CEDULA, cedula);
		Cliente c=(Cliente) q.getSingleResult();
		if(c==null){
			throw new Exception("este cliente no existe");
		}
		return c;
	}
	/**
	 * Metodo para buscar un automovil por su id regristrado en el taller.
	 * @param <id> parametro que contiene el id del cliente necesitado.
	 * @return el automovil con el <id> solicitado en el parametro.
	 */
	public Automovil buscarAutomovilPorID(long id){
		return entityManager.find(Automovil.class, id);
	}
	/**
	 * Metodo para buscar un repuesto por su id registrado en el taller.
	 * @param <id> parametro que contiene el id del repuesto necesitado.
	 * @return el repuesto con el <id> solicitado en el parametro.
	 */
	public Repuesto buscarRepuestoPorID(long id){
		return entityManager.find(Repuesto.class, id);
	}
	
}
